package com.temenos.interaction.jdbc.producer;
/*
* #%L
* interaction-jdbc-producer
* %%
* Copyright (C) 2012 - 2013 Temenos Holdings N.V.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.io.File;
import java.net.URL;
import java.util.Properties;
import javax.naming.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.UriInfo;
import org.h2.jdbcx.JdbcDataSource;
import org.junit.Test;
import org.springframework.jdbc.InvalidResultSetAccessException;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.jndi.JndiTemplate;
import com.temenos.interaction.core.MultivaluedMapImpl;
import com.temenos.interaction.core.command.InteractionContext;
import com.temenos.interaction.core.entity.Entity;
import com.temenos.interaction.core.entity.Metadata;
import com.temenos.interaction.core.hypermedia.ResourceState;
import com.temenos.interaction.core.resource.CollectionResource;
import com.temenos.interaction.core.resource.EntityResource;
import com.temenos.interaction.jdbc.ServerMode;
import com.temenos.interaction.jdbc.exceptions.JdbcException;
import com.temenos.interaction.odataext.odataparser.ODataParser;
/**
* Test JdbcProducer class.
*/
public class TestJdbcProducer extends AbstractJdbcProducerTest {
// Somewhere to store Jndi context.
private JndiTemplate jndiTemplate = null;
// Jndi name for the data source
String DATA_SOURCE_JNDI_NAME = "H2Datasource";
/*
* Utility to set up Jndi context
*/
private void jndiSetUp() {
// Get working directory as a URL.
URL workingDir = null;
boolean threw = false;
try {
File file = new File(System.getProperty("user.dir"));
workingDir = file.toURI().toURL();
} catch (Exception e) {
threw = true;
}
assertFalse("Could not get working directory.", threw);
// Create a jndiTemplate. This will contain a Jndi context.
threw = false;
try {
Properties env = new Properties();
// Uses the local file system for Jndi storage,
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
// Store Jndi information in a .bindings file in the working
// directory.
env.put(Context.PROVIDER_URL, workingDir.toString());
jndiTemplate = new JndiTemplate(env);
} catch (Exception e) {
threw = true;
}
assertFalse("Could not open JndiTemplate", threw);
}
/*
* Utility to shut down Jndi context
*/
private void jndiShutDown() {
try {
// Remove object. If .bindings file becomes empty this should also
// delete it. If not then we have left it as we found it.
jndiTemplate.unbind(DATA_SOURCE_JNDI_NAME);
// Don't think we have to close JndiTemplate
} catch (Exception e) {
fail();
}
}
/**
* Test constructor
*/
@Test
public void testConstructor() {
JdbcProducer producer = null;
try {
producer = new JdbcProducer(dataSource);
} catch (Exception e) {
fail();
}
// Should contain DataSource
assertEquals(dataSource, producer.getDataSource());
}
/**
* Test basic access to database.
*/
@Test
public void testQuery() {
// Populate the database.
populateTestTable();
// Create data source for target
// Create the producer
JdbcProducer producer = null;
try {
producer = new JdbcProducer(dataSource);
} catch (Exception e) {
fail();
}
// Run a query
SqlRowSet rs = producer.query(query);
// Check the results
assertFalse(null == rs);
int rowCount = 0;
while (rs.next()) {
assertEquals(TEST_KEY_DATA + rowCount, rs.getString(KEY_FIELD_NAME));
assertEquals(TEST_VARCHAR_DATA + rowCount, rs.getString(VARCHAR_FIELD_NAME));
assertEquals(TEST_INTEGER_DATA + rowCount, rs.getInt(INTEGER_FIELD_NAME));
rowCount++;
}
assertEquals(TEST_ROW_COUNT, rowCount);
}
/**
* Check that Jndi itself is working
*/
@Test
public void testJndiWorking() {
// Start up Jndi
jndiSetUp();
// Write reference to the data source into Jndi
boolean threw = false;
try {
// Remove any existing objects with same name
jndiTemplate.unbind(DATA_SOURCE_JNDI_NAME);
jndiTemplate.bind(DATA_SOURCE_JNDI_NAME, dataSource);
} catch (Exception e) {
threw = true;
}
assertFalse("Could not bind object to JndiTemplate", threw);
// Test Jndi by reading the object.
threw = false;
JdbcDataSource actualSource = null;
try {
actualSource = (JdbcDataSource) jndiTemplate.lookup(DATA_SOURCE_JNDI_NAME);
} catch (Exception e) {
threw = true;
}
assertFalse("Could not read object from JndiTemplate", threw);
// Check returned data.
assertEquals(dataSource.getUrl(), actualSource.getUrl());
assertEquals(dataSource.getUser(), actualSource.getUser());
assertEquals(dataSource.getPassword(), actualSource.getPassword());
// Tidy
jndiShutDown();
}
/**
* Test access to database with Jndi lookup of datasource
*/
@Test
public void testJndiQuery() {
// Populate the jdbc database.
populateTestTable();
// Start up Jndi
jndiSetUp();
// Write reference to the data source into Jndi
try {
// Remove any existing objects with same name
jndiTemplate.unbind(DATA_SOURCE_JNDI_NAME);
jndiTemplate.bind(DATA_SOURCE_JNDI_NAME, dataSource);
} catch (Exception e) {
fail("Could not bind object to JndiTemplate");
}
// Create the jdbc producer
JdbcProducer producer = null;
try {
producer = new JdbcProducer(jndiTemplate, DATA_SOURCE_JNDI_NAME);
} catch (Exception e) {
fail();
}
// Run a query
SqlRowSet rs = producer.query(query);
// Check the results
assertFalse(null == rs);
int rowCount = 0;
while (rs.next()) {
assertEquals(TEST_KEY_DATA + rowCount, rs.getString(KEY_FIELD_NAME));
assertEquals(TEST_VARCHAR_DATA + rowCount, rs.getString(VARCHAR_FIELD_NAME));
assertEquals(TEST_INTEGER_DATA + rowCount, rs.getInt(INTEGER_FIELD_NAME));
rowCount++;
}
assertEquals(TEST_ROW_COUNT, rowCount);
// Tidy
jndiShutDown();
}
/**
* Test access to database using Iris parameter passing.
*/
@Test
public void testIrisQuery() {
// Populate the database.
populateTestTable();
// Create the producer
JdbcProducer producer = null;
try {
producer = new JdbcProducer(dataSource);
} catch (Exception e) {
fail();
}
// Build up an InteractionContext
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl<String>();
MultivaluedMap<String, String> pathParams = new MultivaluedMapImpl<String>();
InteractionContext ctx = new InteractionContext(mock(UriInfo.class), mock(HttpHeaders.class), pathParams,
queryParams, mock(ResourceState.class), mock(Metadata.class));
// Run a query
SqlRowSet rs = null;
try {
rs = producer.query(TEST_TABLE_NAME, null, ctx);
} catch (Exception e) {
fail();
}
// Check the results
assertFalse(null == rs);
int rowCount = 0;
while (rs.next()) {
assertEquals(TEST_KEY_DATA + rowCount, rs.getString(KEY_FIELD_NAME));
assertEquals(TEST_VARCHAR_DATA + rowCount, rs.getString(VARCHAR_FIELD_NAME));
assertEquals(TEST_INTEGER_DATA + rowCount, rs.getInt(INTEGER_FIELD_NAME));
rowCount++;
}
assertEquals(TEST_ROW_COUNT, rowCount);
}
/**
* Test access to database using Iris parameter passing and returning a
* single entity.
*/
@Test
public void testIrisQueryEntity() {
// Populate the database.
populateTestTable();
// Create the producer
JdbcProducer producer = null;
try {
producer = new JdbcProducer(dataSource);
} catch (Exception e) {
fail();
}
// Build up an InteractionContext
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl<String>();
MultivaluedMap<String, String> pathParams = new MultivaluedMapImpl<String>();
InteractionContext ctx = new InteractionContext(mock(UriInfo.class), mock(HttpHeaders.class), pathParams,
queryParams, mock(ResourceState.class), mock(Metadata.class));
// Run a query
EntityResource<Entity> entityResource = null;
String expectedType = "returnEntityType";
String key = TEST_KEY_DATA + 1;
try {
entityResource = producer.queryEntity(TEST_TABLE_NAME, key, ctx, expectedType);
} catch (Exception e) {
fail();
}
// Check the results
assertFalse(null == entityResource);
Entity entity = (Entity) entityResource.getEntity();
assertEquals(expectedType, entity.getName());
assertEquals(TEST_KEY_DATA + 1, entity.getProperties().getProperty(KEY_FIELD_NAME).getValue());
assertEquals(TEST_VARCHAR_DATA + 1, entity.getProperties().getProperty(VARCHAR_FIELD_NAME).getValue());
assertEquals(TEST_INTEGER_DATA + 1, entity.getProperties().getProperty(INTEGER_FIELD_NAME).getValue());
}
/**
* Test access to database using Iris parameter passing and returning a
* single entity. When the entry is not present in the database.
*/
@Test(expected = JdbcException.class)
public void testIrisQueryEntityMissing() throws Exception {
// Populate the database.
populateTestTable();
// Create the producer
JdbcProducer producer = null;
try {
producer = new JdbcProducer(dataSource);
} catch (Exception e) {
fail();
}
// Build up an InteractionContext
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl<String>();
MultivaluedMap<String, String> pathParams = new MultivaluedMapImpl<String>();
InteractionContext ctx = new InteractionContext(mock(UriInfo.class), mock(HttpHeaders.class), pathParams,
queryParams, mock(ResourceState.class), mock(Metadata.class));
// Run a query. Should throw.
String expectedType = "returnEntityType";
String key = "badEntityKey";
producer.queryEntity(TEST_TABLE_NAME, key, ctx, expectedType);
}
/**
* Test access to database using Iris parameter passing and returning a
* collection of entities.
*/
@Test
public void testIrisQueryEntities() {
// Populate the database.
populateTestTable();
// Create the producer
JdbcProducer producer = null;
try {
producer = new JdbcProducer(dataSource);
} catch (Exception e) {
fail();
}
// Build up an InteractionContext
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl<String>();
MultivaluedMap<String, String> pathParams = new MultivaluedMapImpl<String>();
InteractionContext ctx = new InteractionContext(mock(UriInfo.class), mock(HttpHeaders.class), pathParams,
queryParams, mock(ResourceState.class), mock(Metadata.class));
// Run a query
CollectionResource<Entity> entities = null;
String expectedType = "returnEntityType";
try {
entities = producer.queryEntities(TEST_TABLE_NAME, ctx, expectedType);
} catch (Exception e) {
fail();
}
// Check the results
assertFalse(null == entities);
int entityCount = 0;
for (EntityResource<Entity> entityResource : entities.getEntities()) {
Entity actualEntity = (Entity) entityResource.getEntity();
assertEquals(expectedType, actualEntity.getName());
assertEquals(TEST_KEY_DATA + entityCount, actualEntity.getProperties().getProperty(KEY_FIELD_NAME)
.getValue());
assertEquals(TEST_VARCHAR_DATA + entityCount, actualEntity.getProperties().getProperty(VARCHAR_FIELD_NAME)
.getValue());
assertEquals(TEST_INTEGER_DATA + entityCount, actualEntity.getProperties().getProperty(INTEGER_FIELD_NAME)
.getValue());
entityCount++;
}
assertEquals(TEST_ROW_COUNT, entityCount);
}
/**
* Test access to database using Iris parameters with a $select term.
*/
@Test
public void testIrisSelectQuery() {
// Populate the database.
populateTestTable();
// Create the producer
JdbcProducer producer = null;
try {
producer = new JdbcProducer(dataSource);
} catch (Exception e) {
fail();
}
// Build up an InteractionContext
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl<String>();
queryParams.add(ODataParser.SELECT_KEY, INTEGER_FIELD_NAME);
MultivaluedMap<String, String> pathParams = new MultivaluedMapImpl<String>();
InteractionContext ctx = new InteractionContext(mock(UriInfo.class), mock(HttpHeaders.class), pathParams,
queryParams, mock(ResourceState.class), mock(Metadata.class));
// Run a query
SqlRowSet rs = null;
try {
rs = producer.query(TEST_TABLE_NAME, null, ctx);
} catch (Exception e) {
fail();
}
// Check the results
assertFalse(null == rs);
int rowCount = 0;
while (rs.next()) {
boolean threw = false;
try {
rs.getString(KEY_FIELD_NAME);
} catch (InvalidResultSetAccessException e) {
threw = true;
}
// Not expecting this field so should throw.
assertTrue(threw);
threw = false;
try {
rs.getString(VARCHAR_FIELD_NAME);
} catch (InvalidResultSetAccessException e) {
threw = true;
}
// Not expecting this field so should throw.
assertTrue(threw);
// We are expecting this field.
assertEquals(TEST_INTEGER_DATA + rowCount, rs.getInt(INTEGER_FIELD_NAME));
rowCount++;
}
assertEquals(TEST_ROW_COUNT, rowCount);
}
/**
* Test access to database using Iris with null tablename.
*/
@Test(expected = JdbcException.class)
public void testIrisQueryNullTable() throws Exception {
// Create the producer
JdbcProducer producer = null;
try {
producer = new JdbcProducer(mock(JdbcDataSource.class), ServerMode.MSSQL);
} catch (Exception e) {
fail();
}
// Build up an InteractionContext
MultivaluedMap<String, String> queryParams = new MultivaluedMapImpl<String>();
MultivaluedMap<String, String> pathParams = new MultivaluedMapImpl<String>();
InteractionContext ctx = new InteractionContext(mock(UriInfo.class), mock(HttpHeaders.class), pathParams,
queryParams, mock(ResourceState.class), mock(Metadata.class));
// Run a query. Should throw.
producer.query(null, null, ctx);
}
}